package i18n

import (
	"gitee.com/captials-team/ubdframe/src/common/consts"
	"github.com/BurntSushi/toml"
	"github.com/gin-gonic/gin"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/net/context"
	"golang.org/x/text/language"
	"os"
)

// II18nParser i18n解析器
type II18nParser interface {
	Bundle() *i18n.Bundle
	Load(file, path string) //加解析文件，file=文件路径，path=i18n内path

	Lang(name string) II18nParser //返回对应language的解析器

	CacheLanguages()                   //缓存languages
	Languages() map[string]II18nParser //设置本地化语言

	SetLanguage(lang language.Tag) //设置本地化语言
	SetLocalize(lang string)
	Localize() *i18n.Localizer //获取本地化语言类

	ParseMsg(messageId string, data ...map[string]string) string      //获取i18n解析后的消息
	ParseMsgPanic(messageId string, data ...map[string]string) string //获取i18n解析后的消息（失败会panic）
}

type Parser struct {
	bundle   *i18n.Bundle    //所有语言包的捆绑包
	localize *i18n.Localizer //当前本地化语言

	languages map[string]II18nParser //不同语言对应的本地化语言包
	cache     bool                   //是否已缓存
}

func (i *Parser) Bundle() *i18n.Bundle {
	return i.bundle
}

func (i *Parser) CacheLanguages() {
	if i.cache {
		return
	}
	for _, lang := range i.bundle.LanguageTags() {
		i.languages[lang.String()] = &Parser{
			bundle:   i.bundle,
			localize: i18n.NewLocalizer(i.bundle, lang.String()),
		}
	}
	i.cache = true
}

func (i *Parser) Languages() map[string]II18nParser {
	i.CacheLanguages()

	return i.languages
}

func (i *Parser) Load(file, path string) {
	buf, err := os.ReadFile(file)
	if err != nil {
		panic(err)
	}
	i.bundle.MustParseMessageFileBytes(buf, path)
}

// SetLanguage 设置本地化语言
func (i *Parser) SetLanguage(lang language.Tag) {
	i.SetLocalize(lang.String())
}

func (i *Parser) SetLocalize(lang string) {
	i.localize = i18n.NewLocalizer(i.bundle, lang)
}

func (i *Parser) Localize() *i18n.Localizer {
	return i.localize
}

// Lang 获取对应的i18n语言parser
func (i *Parser) Lang(lang string) II18nParser {
	i.CacheLanguages()

	if l, exist := i.languages[lang]; exist {
		return l
	}

	return i
}

func (i *Parser) ParseMsgPanic(messageId string, data ...map[string]string) string {
	return i.parse(messageId, data...)
}

func (i *Parser) ParseMsg(messageId string, data ...map[string]string) (s string) {
	defer func() {
		//无法解析的原样返回
		if err := recover(); err != nil {
			s = messageId
			return
		}
	}()
	return i.parse(messageId, data...)
}

func (i *Parser) parse(messageId string, data ...map[string]string) string {
	var tmp map[string]string
	if len(data) > 0 {
		tmp = data[0]
	}

	return i.localize.MustLocalize(&i18n.LocalizeConfig{
		MessageID:    messageId,
		TemplateData: tmp,
	})
}

func NewParser() II18nParser {
	bundle := i18n.NewBundle(language.English)
	bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)

	i := &Parser{
		bundle:    bundle,
		languages: map[string]II18nParser{},
	}
	i.SetLanguage(language.English)
	return i
}

func GinHandler() gin.HandlerFunc {
	return func(c *gin.Context) {
		lang := c.GetHeader(consts.AcceptLanguageKey)
		c.Request = c.Request.WithContext(context.WithValue(c, consts.AcceptLanguageKey, lang))
		c.Set(consts.AcceptLanguageKey, lang)
		c.Next()
	}
}

func GetLang(ctx context.Context) string {
	lang, ok := ctx.Value(consts.AcceptLanguageKey).(string)
	if !ok {
		lang = language.English.String()
	}
	return lang
}
